/**
 * this files imports or updates exisiting entries with pubchem compound properties
 */

import edu.ucdavis.genomics.metabolomics.binbase.connector.references.pubchem.PubchemSubstanceSDFResolver
import org.apache.log4j.Logger
import edu.ucdavis.genomics.metabolomics.binbase.connector.references.sdf.*
import compound.repository.entries.*
import types.GenerateDomainClassStatement
import java.util.zip.GZIPInputStream
import util.CompoundHelper

//configuration file
def config = new ConfigSlurper().parse(new File('grails-app/conf/PathConfiguration.groovy').toURL())

Logger logger = Logger.getLogger("ImportPubchem")


if (params.file == null) {
  logger.info "using directory mode..."

  String tempDir = config.files.pubchem.substance

  FileHelper.workOnDir(tempDir, {File file ->
    PubchemInchiSubstance sub = new PubchemInchiSubstance()
    SdfToInchi.sdfToInchi(new FileInputStream(file), sub)

  }, logger, ".sdf")
}
else {
  logger.info "using direct file mode: ${params.file}"
  File file = new File(params.file)

  InputStream stream = null
  if (file.name.endsWith(".sdf.gz")) {

    stream = new GZIPInputStream(new FileInputStream(file))
  }

  else if (file.name.endsWith(".sdf")) {
    stream = new FileInputStream(file)

  }
  else {

    throw new RuntimeException("it needs to be a 'sdf' file or a 'sdf.gz' file ")
  }

  PubchemInchiSubstance sub = new PubchemInchiSubstance()
  SdfToInchi.sdfToInchi(new BufferedInputStream(stream), sub)

  stream.close()
}

/**
 * imports a pubchem compound for each found inchi
 */
class PubchemInchiSubstance implements InchFinder {


  public void foundInchi(String myInchi, Map<java.lang.Object, java.lang.Object> objectObjectMap) throws Exception {

    Logger logger = Logger.getLogger("ImportPubchem")
    logger.debug "checking if inchi is acceptable"
    logger.debug "map: ${objectObjectMap}"

    if (myInchi != null && myInchi.size() > 0) {

      PubchemSubstanceSDFResolver resolver = new PubchemSubstanceSDFResolver()
      resolver.prepare(objectObjectMap)

      Compound compound = CompoundHelper.getCompound(resolver.getInchi(), resolver.getInchiKey(), logger)

      //save the cas number, if it's available
      CompoundHelper.updatesTheCasNumber(resolver.getCas(), compound, logger)

      //sets the sid for this compound
      CompoundHelper.updateSID(logger, compound, Integer.parseInt(resolver.getSid()))

      List<String> syn = resolver.getSynonyms()

      syn.remove(resolver.getExtDatasourceName())
      syn.remove(resolver.getExtRegId())

      logger.info "Adding synonyms..."

      if(syn != null){
      syn.each{
        logger.info it
      }
      }
        
      CompoundHelper.addSynonym(syn, logger, compound)
      CompoundHelper.updatesTheCasNumber(resolver.getCas(), compound, logger)

      logger.info "Working on dblinks"
      def link = DBLinks.findAllByLinkIDAndSourceName(resolver.getExtRegId(), resolver.getExtDatasourceName())

      logger.info link


      if (link == null | link.size() == 0) {
        String name = "compound.repository.entries.${GenerateDomainClassStatement.cleanClassName(resolver.getExtDatasourceName())}"
        logger.info "trying to initialize ${name}"

        try {
          def init = Class.forName(name, true, Thread.currentThread().getContextClassLoader()).newInstance()

          if (init instanceof DBLinks) {
            logger.info "adding a new dblink to the system"
            DBLinks l = init

            l.compound = compound
            l.linkID = resolver.getExtRegId()
            l.sourceName = resolver.getExtDatasourceName()
            l.populate()
            l.save()
          }
          else {
            logger.info "sorry the class ${name} needs to extend from DBLinks"
          }
        }
        catch (ClassNotFoundException e) {
          logger.info "sorry this dblink class does not exist, please create a new domain class which is extending from DBLinks"

        }
        catch (Exception e) {
          logger.error e.getMessage(), e
        }
      }

      logger.info "persist in database"

      //save the compound to the database
      CompoundHelper.saveCompound(compound, logger)


      CompoundHelper.aquireStatistic()

      logger.info "compound finished"

    }
  }

}